{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# 关于 Tensor"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 常见的Tensor"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(42.) 0 42.0\n",
      "tensor([ 1.5000, -0.5000,  3.0000]) 1 torch.Size([3])\n",
      "tensor([[1, 2],\n",
      "        [3, 4]])\n",
      "tensor([[ 7, 10],\n",
      "        [15, 22]])\n",
      "tensor([[ 1,  4],\n",
      "        [ 9, 16]])\n"
     ]
    }
   ],
   "source": [
    "from torch import tensor\n",
    "# Scalar 通常是个值\n",
    "x = tensor(42.)\n",
    "print(x, x.dim(),x.item())\n",
    "# Vector 向量，表示特征\n",
    "v = tensor([1.5,-0.5,3.0])\n",
    "print(v, v.dim(),v.size())\n",
    "# Matrix 一般计算的都是矩阵 多行\n",
    "m = tensor([[1,2],[3,4]])\n",
    "print(m)\n",
    "print(m.matmul(m)) # 内积\n",
    "print(m*m) # 乘法\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Tensor的数据类型\n",
    "\n",
    "###  32位浮点型：torch.FloatTensor (Tensor默认的数据类型)"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import torch"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "a = torch.Tensor( [[2,3],[4,8],[7,9]], )\n",
    "print(a)\n",
    "print('size:', a.size())\n",
    "print('dtype:', a.dtype)\n",
    "\n",
    "b=torch.FloatTensor( [[2,3],[4,8],[7,9]] )\n",
    "print(b)\n",
    "print('size:', b.size())\n",
    "print('dtype:', b.dtype)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 64位浮点型：torch.DoubleTensor"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# b = torch.DoubleTensor( [[2,3],[4,8],[7,9]] )\n",
    "b = torch.Tensor( [True, True, False])\n",
    "print(b)\n",
    "print('size:', b.size(), 'dtype:', b.dtype)\n",
    "size = b.size()\n",
    "c = size[0]\n",
    "print(c)\n",
    "for i,t in enumerate(b):\n",
    "    print(i, t )\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 16位整型：torch.ShortTensor"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "b=torch.ShortTensor( [[2,3],[4,8],[7,9]] )\n",
    "print(b)\n",
    "print('size:', b.size(), 'dtype:', b.dtype)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 32位整型：torch.IntTensor"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "b=torch.IntTensor( [[2,3],[4,8],[7,9]] )\n",
    "print(b)\n",
    "print('size:', b.size(), 'dtype:', b.dtype)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 64位整型：torch.LongTensor"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "b=torch.LongTensor( [[2,3],[4,8],[7,9]] )\n",
    "print(b)\n",
    "print('size:', b.size(), 'dtype:', b.dtype)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 布尔类型：torch.BoolTensor"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "b = torch.BoolTensor( [True, True, False])\n",
    "print(b.int())\n",
    "print(b)\n",
    "print('size:', b.size(), 'dtype:', b.dtype)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "n = np.array([])\n",
    "a = torch.FloatTensor([1,2,3.2])\n",
    "print(a)\n",
    "print(a[0].numpy())\n",
    "c = np.append(b,0)\n",
    "print(c[0])\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "##  类型转换\n",
    "\n",
    "1. 数据类型转换\n",
    "    * 在Tensor后加 .long(), .int(), .float(), .double()等即可，也可以用.to()函数进行转换，所有的Tensor类型可参考https://pytorch.org/docs/stable/tensors.html\n",
    "2. 数据存储位置转换\n",
    "    * CPU张量 ---->  GPU张量，使用data.cuda()\n",
    "    * GPU张量 ----> CPU张量，使用data.cpu()\n",
    "3. 与numpy数据类型转换\n",
    "    * Tensor---->Numpy  使用 data.numpy()，data为Tensor变量\n",
    "    * Numpy ----> Tensor 使用 torch.from_numpy(data)，data为numpy变量\n",
    "4. 与Python数据类型转换\n",
    "    * Tensor ----> 单个Python数据，使用data.item()，data为Tensor变量且只能为包含单个数据\n",
    "    * Tensor ----> Python list，使用data.tolist()，data为Tensor变量，返回shape相同的可嵌套的list"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 更改Tensor的数据类型"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "a=torch.FloatTensor( (3,2) )\n",
    "print(a)\n",
    "print('size:', a.size(), 'dtype:', a.dtype)\n",
    "\n",
    "b= a.int()\n",
    "print(b)\n",
    "print('size:', b.size(), 'dtype:', b.dtype)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Tensor和numpy数组转换"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a = torch.randn( size=(4,5),dtype=torch.float32 ) # Tensor转numpy\n",
    "print(a)\n",
    "print('size:', a.size(), 'dtype:', a.dtype)\n",
    "\n",
    "b = a.numpy()\n",
    "print(b)\n",
    "print('size:', b.shape, 'dtype:', b.dtype)\n",
    "\n",
    "c = np.random.randn(3,4) # numpy转Tensor\n",
    "print(c)\n",
    "print('size:', c.shape, 'dtype:', c.dtype)\n",
    "\n",
    "d=torch.from_numpy( c )\n",
    "print(d)\n",
    "print('size:', d.size(), 'dtype:', d.dtype)\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Tensor和 python数据类型的转换"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "a = torch.randn( size=(4,5),dtype=torch.float32 ) # Tensor转numpy\n",
    "print('size:', a.size(), 'dtype:', a.dtype)\n",
    "b = a.tolist()\n",
    "print(b)\n",
    "print('type:', type(b))\n",
    "\n",
    "a = torch.randn( size=(4,1),dtype=torch.float32 ) # Tensor转numpy\n",
    "print(a)\n",
    "print('size:', a.size(), 'dtype:', a.dtype)\n",
    "b = a[0].item()\n",
    "print(b)\n",
    "print('type:', type(b))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 快速创建Tensor"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 特殊tensor\n",
    "* torch.zeros\n",
    "* torch.ones\n",
    "* torch.arange 根据start与stop指定的范围以及step设定的步长，生成一个array"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 1. 全为0 a\n",
    "t=torch.zeros( size=(4,5),dtype=torch.float32 )\n",
    "print('全为0 ',t)\n",
    "print('size:', t.size(), 'dtype:', t.dtype)\n",
    "print('全为1 ', torch.ones(size=(3,4)))\n",
    "print('顺序 ', torch.arange(1,11))\n",
    "print('步长0.1 ', torch.arange(1,2,0.1))\n",
    "print('步长-0.1 ', torch.arange(1,0, -0.1))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 生成随机数Tensor的方法\n",
    " * torch.rand() 均匀分布, 从区间[0, 1)的均匀分布中抽取的一组随机数\n",
    " * torch.randn() 标准正态分布, 从标准正态分布（均值为0，方差为1，即高斯白噪声）中抽取的一组随机数\n",
    " * torch.normal(means, std, out=None) → Tensor 离散正态分布,从指定均值means和标准差std的离散正态分布中抽取的一组随机数\n",
    " * ttorch.linspace(start, end, steps=100, out=None) → Tensor 线性间距向量, 在区间start和end上均匀间隔的step个点"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "t = torch.rand(size=(4,5))\n",
    "print(t)\n",
    "print('size:', t.size(), 'dtype:', t.dtype)\n",
    "t = torch.randn(2, 3)\n",
    "print(t)\n",
    "\n",
    "t = torch.normal(mean=torch.full([10],0.), std=torch.arange(1, 0.0,-0.1))\n",
    "print(t)\n",
    "t = torch.linspace(3, 10, steps=5)\n",
    "print(t)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Tensor的比较\n",
    "> Tensor本身就可以进行一些比较, 更详细的资料大家可以去阅读官方文档。\n",
    "\n",
    "* 等于 torch.equal(tensor1, tensor2) → bool\n",
    "    > 如果两个张量的尺寸和元素都相同，则返回True，否则返回False。\n",
    "* 大于 torch.gt(input, other, out=None) → Tensor\n",
    "* 大于等于 torch.ge(input, other, out=None) → Tensor"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(torch.equal(torch.Tensor([1, 2]), torch.Tensor([1, 2])))\n",
    "print(torch.gt(torch.Tensor([1, 2]), torch.Tensor([1, 2])))\n",
    "# print(torch.gt(torch.Tensor([1, 2, 3]), torch.Tensor([1, 2]))) RuntimeError:  size 要一致\n",
    "print(torch.gt(torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[1, 1], [4, 4]])))\n",
    "print(torch.gte(torch.Tensor([1, 2]), torch.Tensor([1, 2])))\n",
    "\n",
    "\n",
    "### 2.4.3 修改Tensor形状\n",
    "\n",
    "|函数|描述|\n",
    "|:----|:----|\n",
    "| size() | 返回张量的shape属性\n",
    "| numel(input) | tensor的元素个数\n",
    "| view(*shape) | 修改张量的shape属性（view返回的对象与源tensor共享内存，修改一个另一个也被修改。reshape生成新张量） View(-1)展平数组\n",
    "| resize | 类似view，在size超过时，重新分配内存空间\n",
    "| item | 若tensor为单元素，返回python的标量\n",
    "| unsqueeze | 指定维度增加一个 1\n",
    "| squeeze | 指定维度压缩一个 1\n",
    "\n",
    "【说明】torch.view与torch.reshpae的异同\n",
    "\n",
    "1. reshape()可以由torch.reshape(),也可由torch.Tensor.reshape()调用。view()只可由torch.Tensor.view()来调用。\n",
    "2. 对于一个将要被view的Tensor，新的size必须与原来的size与stride兼容。否则，在view之前必须调用contiguous()方法。\n",
    "3. 同样也是返回与input数据量相同，但形状不同的tensor。若满足view的条件，则不会copy，若不满足，则会copy\n",
    "4. 如果您只想重塑张量，请使用torch.reshape。 如果您还关注内存使用情况并希望确保两个张量共享相同的数据，请使用torch.view"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "#生成一个形状为2x3的矩阵\n",
    "x = torch.randn(2, 3)\n",
    "print(x)\n",
    "print( x.size())    # torch.Size([2, 3])\n",
    "print( x.dim() )    # 2\n",
    " # 把x变为3x2的矩阵\n",
    "print(x.view(3,2))\n",
    "y=x.view(-1)  #把x展平为1维向量\n",
    "print(y)\n",
    "\n",
    "z = torch.unsqueeze(y,0) # 添加一个维度\n",
    "print(z)\n",
    "print(z.size(), z.numel()) # 查看z的形状 和元素个数"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.4.4 索引操作\n",
    "\n",
    "|函数|描述|\n",
    "|:----|:----|\n",
    "| index_select(input,dim,index) | 指定维度上，选择列或行\n",
    "| nonzero(input) | 获取非0下标\n",
    "| masked_select(input,mask) | 使用二元值进行选择\n",
    "| gather(input, dim, index) | 指定维度选择数据，形状和index（LongTensor类型）一致\n",
    "| scatter_(input,dim,index,src) | gather的反操作，根据指定索引补充数据"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "#设置一个随机种子\n",
    "torch.manual_seed(100)\n",
    "#生成一个形状为2x3的矩阵\n",
    "x = torch.randn(2, 3)\n",
    "#根据索引获取第1行，所有数据\n",
    "x[0,:]\n",
    "#获取最后一列数据\n",
    "x[:,-1]\n",
    "#生成是否大于0的Byter张量\n",
    "mask = x > 0\n",
    "# 获取大于0的值\n",
    "t = torch.masked_select(x,mask)\n",
    "print(t)\n",
    "# 获取非0下标,即行，列索引\n",
    "t = torch.nonzero(mask)\n",
    "print(t)\n",
    "#获取指定索引对应的值,输出根据以下规则得到\n",
    "#out[i][j] = input[index[i][j]][j]  # if dim == 0\n",
    "#out[i][j] = input[i][index[i][j]]  # if dim == 1\n",
    "index = torch.LongTensor([[0,1,1]])\n",
    "a = torch.gather(x,0,index)\n",
    "print(a)\n",
    "index = torch.LongTensor([[0,1,1],[1,1,1]])\n",
    "b = torch.gather(x,1,index)\n",
    "print(b)\n",
    "# 把a的值返回到一个2x3的0矩阵中\n",
    "z = torch.zeros(2,3)\n",
    "z.scatter_(1,index,b)\n",
    "print(z)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.4.5 广播机制"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "\n",
    "A = np.arange(0, 40,10).reshape(4, 1)\n",
    "B = np.arange(0, 3)\n",
    "#把ndarray转换为Tensor\n",
    "A1=torch.from_numpy(A)  #形状为4x1\n",
    "B1=torch.from_numpy(B)  #形状为3\n",
    "#Tensor自动实现广播\n",
    "C=A1+B1\n",
    "#我们可以根据广播机制，手工进行配置\n",
    "#根据规则1，B1需要向A1看齐，把B变为（1,3）\n",
    "B2=B1.unsqueeze(0)  #B2的形状为1x3\n",
    "#使用expand函数重复数组，分别的4x3的矩阵\n",
    "A2=A1.expand(4,3)\n",
    "B3=B2.expand(4,3)\n",
    "#然后进行相加,C1与C结果一致\n",
    "C1=A2+B3"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.4.6 逐元素操作\n",
    "\n",
    "|函数|描述|\n",
    "|:----|:----|\n",
    "| abs / add  | 绝对值、加\n",
    "| addcdiv(t,v,t1,t2)  | t1与t2的按元素除后，乘v加t\n",
    "| addcmul(t,v,t1,t2)  | t1与t2的按元素乘后，乘v加t\n",
    "| ceil / floor  | 向上取整 向下取整\n",
    "| clamp(t,min,max)  | 张量限制在指定区间\n",
    "| exp / log / pow  | 指数，对数，幂\n",
    "| mul / neg   | 逐个元素乘法 / 取反\n",
    "| sigmoid / tanh / softmax  | 激活函数\n",
    "| sign / sqrt  | 取符号 / 开根号\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "t = torch.randn(1, 3)\n",
    "t1 = torch.randn(3, 1)\n",
    "t2 = torch.randn(1, 3)\n",
    "#t+0.1*(t1/t2)\n",
    "torch.addcdiv(t, 0.1, t1, t2)\n",
    "#计算sigmoid\n",
    "torch.sigmoid(t)\n",
    "#将t限制在[0,1]之间\n",
    "torch.clamp(t,0,1)\n",
    "#t+2进行就地运算\n",
    "t.add_(2)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.4.7 归并操作\n",
    "归并就是对输入进行归并或合计等操作\n",
    "\n",
    "这类操作的输入输出形状一般不相同，而且往往是输入大于输出形状。归并操作可以对整个tensor，也可以沿着某个维度进行归并。\n",
    "\n",
    "|函数|描述|\n",
    "|:----|:----|\n",
    "| cumprod(t, axis) | 指定维度的t累乘积\n",
    "| cumsum | 指定维度的t累加\n",
    "| dist(a,b,p=2)| 返回a，b之间的p阶范数\n",
    "| mean / median  | 均值，中位数\n",
    "| std / var | 标准差 / 方差\n",
    "| norm(t,p=2)  | t的p阶范数\n",
    "| prod(t) / sum(t)| 所有元素的 积 / 和\n",
    "\n",
    "> 归并操作一般涉及一个dim参数，指定沿哪个维进行归并。\n",
    "> 另一个参数是keepdim，说明输出结果中是否保留维度1，缺省情况是False，即不保留。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "#生成一个含6个数的向量\n",
    "a=torch.linspace(0,10,6)\n",
    "#使用view方法，把a变为2x3矩阵\n",
    "a=a.view((2,3))\n",
    "#沿y轴方向累加，即dim=0\n",
    "b=a.sum(dim=0)   #b的形状为[3]\n",
    "#沿y轴方向累加，即dim=0,并保留含1的维度\n",
    "b=a.sum(dim=0,keepdim=True) # b的形状为[1,3]"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.4.8 比较操作\n",
    "比较操作一般进行逐元素比较，有些是按指定方向比较。\n",
    "\n",
    "|函数|描述|\n",
    "|:----|:----|\n",
    "| eq | 是否相等，支持广播\n",
    "| equal | 是否相同的shape和值\n",
    "| ge /le /gt/lt| 大于等，小于等，大于，小于\n",
    "| max /min(t,axis) | 最值\n",
    "| topk(t,k,axis) | 指定axis维上取最高的k个值"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "x=torch.linspace(0,10,6).view(2,3)\n",
    "#求所有元素的最大值\n",
    "torch.max(x)   #结果为10\n",
    "#求y轴方向的最大值\n",
    "torch.max(x,dim=0)  #结果为[6,8,10]\n",
    "#求最大的2个元素\n",
    "torch.topk(x,1,dim=0)  #结果为[6,8,10],对应索引为tensor([[1, 1, 1]"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.4.9 矩阵操作\n",
    "\n",
    " |函数|描述|\n",
    " |:----|:----|\n",
    " | dot(t1,t2) | 计算张量的内积，点积\n",
    " | mm(mat1,mat2) / bmm(batch1,batch2) | 计算矩阵乘法/含batch的3D矩阵乘法\n",
    " | mv(t1,v1) | 计算矩阵与向量乘法\n",
    " | t | 转置\n",
    " | svd(t) | SVD分解\n",
    "\n",
    "【说明】\n",
    "1. torch的dot与Numpy的dot有点不同，torch中dot对两个为1D张量进行点积运算，Numpy中的dot无此限制。\n",
    "2. mm是对2D的矩阵进行点积，bmm对含batch的3D进行点积运算。\n",
    "3. 转置运算会导致存储空间不连续，需要调用contiguous方法转为连续。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "a = torch.tensor([2, 3])\n",
    "b = torch.tensor([3, 4])\n",
    "print( torch.dot(a,b)) # 运行结果为18\n",
    "\n",
    "x = torch.randint(10,(2,3))\n",
    "y = torch.randint(6,(3,4))\n",
    "print(x)\n",
    "print(y)\n",
    "print(torch.mm(x,y))\n",
    "x = torch.randint(10,(2,2,3))\n",
    "y = torch.randint(6,(2,3,4))\n",
    "print(torch.bmm(x,y))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.4.10 Pytorch与Numpy比较\n",
    "\n",
    "| 操作类别 |Numpy| PyTorch |\n",
    "|:----|:----|:----|\n",
    "| 数据类型 | np.ndarray | torch.Tensor |\n",
    "| - | np.float32 | torch.float32,torch.float |\n",
    "| - | np.float64 | torch.float64,torch.double |\n",
    "| - | np.float64 | torch.float64,torch.double |\n",
    "| - | np.int64 | torch.int64,torch.long |\n",
    "| 数据构建 | np.ndarray([1,2,3,4],dytpye=np.float16) | torch.tensor([1,2,3,4],dtype=torch.float16) |\n",
    "| - | c.copy() | x.clone() |\n",
    "| - | np.concatenate | torch.cat |\n",
    "| 线性代数 | np.dot | torch.mm |\n",
    "| 属性 | x.ndim | x.dim() |\n",
    "| 属性 | x.size | x.nelement() |\n",
    "| 形状操作 | x.reshape | x.reshape(),x.view() |\n",
    "| - | x.flatter | x.view(-1) |\n",
    "| 类型转换 | np.floor(x) | torch.floor(x), x.floor() |\n",
    "| 比较 | np.less | x.lt |\n",
    "| - | np.less_equal, np.greater | x.le, x.gt |\n",
    "| - | np.greater_equal, np.equal, np.not_equal | x.gt,x.eq,x.ne |\n",
    "| 随机种子 | np.random.seed | torch.manual_seed |\n"
   ],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}